#include "dht11.h"
#include "delay.h"


void DHT11_Mode_IPU(void);
void DHT11_Mode_Out_PP(void);
uint8_t DHT11_ReadByte(void);


/*DHT11温湿度传感器-DATA引脚为PE-6 */
/*请在此处补充GPIO初始化配置信息 */
void DHT11_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;                  /*定义一个GPIO_InitTypeDef类型的结构体*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); /*开启GPIOE的外设时钟*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;             /*选择要控制的GPIOE引脚*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     /*设置引脚速率为50MHz */
    GPIO_Init(GPIOE, &GPIO_InitStructure);                /*调用库函数，初始化GPIOE*/
    GPIO_SetBits(GPIOE, GPIO_Pin_6); // 拉高GPIOB10
}
/* END */

/*请在此处补充配置信息，使DHT11-DATA引脚变为上拉输入模式 */
void DHT11_Mode_IPU(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;          /*选择要控制的GPIOE引脚*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;     /*设置引脚模式为浮空输入模式*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /*调用库函数，初始化GPIOE*/
    GPIO_Init(GPIOE, &GPIO_InitStructure);
}
/* END */


/*请在此处补充配置信息，使DHT11-DATA引脚变为推挽输出模式 */
void DHT11_Mode_Out_PP(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;         /*选择要控制的GPIOE引脚*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*设置引脚速率为50MHz */
    GPIO_Init(GPIOE, &GPIO_InitStructure);            /*调用库函数，初始化GPIOE*/
}
/* END */

/*请在此处补充信息，从DHT11读取一个字节 */
/*请在此处补充信息，从DHT11读取一个字节 */
uint8_t DHT11_ReadByte(void)
{
    uint8_t i, temp = 0;
    for (i = 0; i < 8; i++)
    {
        /*每bit以50us低电平标置开始，轮询直到从机发出 的50us 低电平 结束*/
        while (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_6) == Bit_RESET);
        /*DHT11 以26~28us的高电平表示“0”，以70us高电平表示“1”，
         *通过检测 x us后的电平即可区别这两个状 ，x 即下面的延时 
         */
        delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可
        if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_6) == Bit_SET) /* x us后仍为高电平表示数据“1” */
        {
            /* 等待数据1的高电平结束 */
            while (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_6) == Bit_SET);
            temp |= (uint8_t)(0x01 << (7 - i)); //把第7-i位置1，MSB先行
        }
        else // x us后为低电平表示数据“0”
        {
            temp &= (uint8_t) ~(0x01 << (7 - i)); //把第7-i位置0，MSB先行
        }
    }
    return temp;
}
/*请在此处补充信息，完成一次完整的DHT11数据传输 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
    DHT11_Mode_Out_PP();               /*输出模式*/
    GPIO_ResetBits(GPIOE, GPIO_Pin_6); /*主机拉低*/
    delay_ms(18);                      /*延时18ms*/
    GPIO_SetBits(GPIOE, GPIO_Pin_6);   /*总线拉高 主机延时30us*/
    delay_us(30);                      //延时30us
    DHT11_Mode_IPU();                  /*主机设为输入 判断从机响应信号*/
    /*判断从机是否有低电平响应信号 如不响应则跳出，响应则向下运行*/
    if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_6) == Bit_RESET)
    {
        /*轮询直到从机发出 的80us 低电平 响应信号结束*/
        while (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_6) == Bit_RESET);
        /*轮询直到从机发出的 80us 高电平 标置信号结束*/
        while (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_6) == Bit_SET);
        /*开始接收数据*/
        DHT11_Data->humi_int = DHT11_ReadByte();
        DHT11_Data->humi_deci = DHT11_ReadByte();
        DHT11_Data->temp_int = DHT11_ReadByte();
        DHT11_Data->temp_deci = DHT11_ReadByte();
        DHT11_Data->check_sum = DHT11_ReadByte();
        DHT11_Mode_Out_PP();             /*读取结束，引脚改为输出模式*/
        GPIO_SetBits(GPIOE, GPIO_Pin_6); /*主机拉高*/
        /*检查读取的数据是否正确*/
        if (DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci)
            return SUCCESS;
        else
            return ERROR;
    }
    else
        return ERROR;
}